//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
                                                      
#include "CIISNetInterface.h"
#include "limits.h"
#include "math.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)


__fastcall TCIISNetInterface::TCIISNetInterface(TCIISDBModule *SetDB,
                                                          TDebugWin *SetDebugWin,
                                                          String SetCtrl)
{
  DB = SetDB;
  DW = SetDebugWin;
  Ctrl = SetCtrl;
  NoOpts.Clear();

  CAN = new TUSBCANInterface( &ProcessMessage, DW );

  DB->TabControllers->Locate( "CtrlName", Ctrl, NoOpts );
  DB->TabControllers->Edit();
  DB->TabControllers->FieldValues["NodeCount"] = 0;
  DB->TabControllers->FieldValues["MonitorCount"] = 0;
  DB->TabControllers->FieldValues["DecayCount"] = 0;
  DB->TabControllers->FieldValues["LPRCount"] = 0;
  DB->TabControllers->Post();

  ScheduleDateTime = DB->TabControllers->FieldByName("ScheduleDateTime")->AsDateTime;
  ScheduleStatus = DB->TabControllers->FieldByName("CtrlScheduleStatus")->AsInteger;
  TSys = 0;

  Monitors = new TList;
  Decays = new TList;
	LPRs = new TList;
	UPSs = new TList;

	TimerUpdateAlarm = new TTimer( NULL );
	TimerUpdateAlarm->Enabled = false;
	TimerUpdateAlarm->Interval = UpdateAlarmDelay;
	TimerUpdateAlarm->OnTimer = TimerUpdateAlarmsEvent;

  TimerCapabilityReq = new TTimer(NULL);
  TimerCapabilityReq->Enabled = false;
  TimerCapabilityReq->Interval = CapabilityReqDelay;
  TimerCapabilityReq->OnTimer = TimerCapabilityReqEvent;

	TimerSetCANGroup = new TTimer(NULL);
  TimerSetCANGroup->Enabled = false;
  TimerSetCANGroup->Interval = SetCANGroupDelay;
  TimerSetCANGroup->OnTimer = TimerSetCANGroupEvent;

	TimerVerReq = new TTimer(NULL);
	TimerVerReq->Enabled = false;
	TimerVerReq->Interval = VerReqDelay;
	TimerVerReq->OnTimer = TimerVerReqEvent;

	TimerIShuntReq = new TTimer(NULL);
  TimerIShuntReq->Enabled = false;
  TimerIShuntReq->Interval = IShuntReqDelay;
	TimerIShuntReq->OnTimer = TimerIShuntReqEvent;

  TimerRestart = new TTimer(NULL);
  TimerRestart->Enabled = false;
	TimerRestart->Interval = RestartDelay;
  TimerRestart->OnTimer = TimerRestartEvent;

  TimerSClock = new TTimer(NULL);
	TimerSClock->Enabled = false;
	TimerSClock->Interval = SysClock / 2;
	TimerSClock->OnTimer = TimerSClockEvent;

	TimerUpdatePS = new TTimer( NULL );
	TimerUpdatePS->Enabled = false;
	TimerUpdatePS->Interval = UpdatePSDelay;
	TimerUpdatePS->OnTimer = TimerUpdatePSEvent;



  #if DebugNetIntLocal == 1
  Debug("CIISNetInterface Created");
  #endif

}

//---------------------------------------------------------------------------

__fastcall TCIISNetInterface::~TCIISNetInterface()
{
TCIISMonitor *M;
TCIISDecay *D;
TCIISLPR *LPR;
TCIISUpdatePS *UPS;

CAN->CanBusOff();

delete TimerUpdateAlarm;
delete TimerCapabilityReq;
delete TimerSetCANGroup;
delete TimerIShuntReq;
delete TimerRestart;
delete TimerSClock;

for( int i = 0; i < Monitors->Count; i++)
{
  M = (TCIISMonitor*)Monitors->Items[i];
  Monitors->Delete( i );
  delete M;
}
delete Monitors;

for( int i = 0; i < Decays->Count; i++)
{
  D = (TCIISDecay*)Decays->Items[i];
  Decays->Delete( i );
  delete D;
}
delete Decays;

for( int i = 0; i < LPRs->Count; i++)
{
	LPR = (TCIISLPR*)LPRs->Items[i];
	LPRs->Delete( i );
	delete LPR;
}
delete LPRs;

for( int i = 0; i < UPSs->Count; i++)
{
	UPS = (TCIISUpdatePS*)UPSs->Items[i];
	UPSs->Delete( i );
	delete UPS;
}
delete UPSs;

delete CAN;
       //TODO: Add your source code here
}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::ProcessMessage(const Byte *CANInMsg)
{
int RecType, RecordingNo, AlarmStatus1, AlarmStatus2;
Cardinal SerNo;
Word CanAdr, MessageId;
Byte Tag, ZoneNo; 
int SensorLPRStep;
Smallint ADVal1, ADVal2;
unsigned short UADVal1, UADVal2;
int ADVal;
double AnVal1, AnVal2, AnVal1_Scl, AnVal2_Scl, LowLev1, HighLev1, LowLev2, HighLev2, IShunt;
bool StatusChanged;
TDateTime DTS1, DTS2;

MessageId = CANInMsg[1] + CANInMsg[2]*256;

switch (CANInMsg[0])
{
  case MSG_TX_IDENTIFY:
  SerNo = CANInMsg[1] + CANInMsg[2]*256 + CANInMsg[3]*65536;
  #if DebugNetIntLocal == 1
  Debug( "Request from " + IntToStr( SerNo ) );
  #endif

  if (!DB->TabNodes->Locate( "NodeSerialNo", SerNo, NoOpts ))
  {
    DB->TabNodes->Append();
    DB->TabNodes->FieldValues["NodeSerialNo"] = SerNo;
    DB->TabNodes->FieldValues["NodeCanAdr"] = 0;
    DB->TabNodes->FieldValues["NodeType"] = 0;
		DB->TabNodes->FieldValues["NodeStatus"] = 0;
    DB->TabNodes->FieldValues["NodeConnected"] = false;
    DB->TabNodes->Post();

    DB->TabProject->Edit();
		DB->TabProject->FieldValues["ConfigVer"] = DB->TabProject->FieldByName("ConfigVer")->AsInteger + 1;
    DB->TabProject->Post();

  }
  else
  {
    DB->TabNodes->Edit();
    DB->TabNodes->FieldValues["NodeType"] = 0;
		DB->TabNodes->FieldValues["NodeStatus"] = 0;
    DB->TabNodes->FieldValues["NodeConnected"] = false;
    DB->TabNodes->Post();

    if (( !DB->TabSensors->Locate( "SensorSerialNo", SerNo, NoOpts )) &&
        ( !DB->TabPowerSupply->Locate( "PSSerialNo", SerNo, NoOpts )))
    { // In node table but not in Sensor or PowerSupply table ????
      DB->TabNodes->Edit();
      DB->TabNodes->FieldValues["NodeSerialNo"] = SerNo;
      DB->TabNodes->FieldValues["NodeCanAdr"] = 0;
      DB->TabNodes->FieldValues["NodeType"] = 0;
			DB->TabNodes->FieldValues["NodeStatus"] = 0;
      DB->TabNodes->FieldValues["NodeConnected"] = false;
      DB->TabNodes->Post();
    }
  }

  CanAdr = DB->TabNodes->FieldByName("NodeCanAdr")->AsInteger;

  if( CanAdr == 0 )
  {
   CanAdr = GetCanAdr();
   DB->TabNodes->Edit();
   DB->TabNodes->FieldValues["NodeCanAdr"] = CanAdr;
   DB->TabNodes->Post();
	}

	SendAccept( SerNo, CanAdr); // ZoneNo not set yet. Accept must be sent to current ZoneNo
	TimerCapabilityReq->Enabled = True;
	break;

	case MSG_TX_ANALOG: ;
	break;

	case MSG_TX_LPR:
	DB->TabSensors->Locate("SensorCanAdr", MessageId, NoOpts);
	IShunt = DB->TabSensors->FieldByName("SensorIShunt")->AsFloat;
	ZoneNo = DB->TabSensors->FieldByName("ZoneNo")->AsInteger;
	SensorLPRStep = DB->TabSensors->FieldByName("SensorLPRStep")->AsInteger;
	SensorLPRStep++;
	DB->TabZones->Locate("ZoneNo", ZoneNo, NoOpts );
	RecordingNo = DB->TabZones->FieldByName("RecNo")->AsInteger;

	ADVal1 = CANInMsg[5]+CANInMsg[6]*256;
	ADVal2 = CANInMsg[3]+CANInMsg[4]*256;
	AnVal1 = ADVal1; AnVal1 = AnVal1 * 1000 * 5 / 65535;
	AnVal2 = ADVal2; AnVal2 = AnVal2 * 1000 * 5 / 65535 / IShunt;
	/*
	AnVal1 = (5/65535)*ADVal1*1000;
	AnVal2 = (5/65535)*ADVal2/IShunt*1000;
	*/
	DB->TabSensors->Edit();
	DB->TabSensors->FieldValues["SensorLastValue"] = AnVal1;
	DB->TabSensors->FieldValues["SensorLPRStep"] = SensorLPRStep;
	DB->TabSensors->Post();

	// If time has been set back store value last in tab.
	DTS1 = Now();
	DB->TabValuesLPR->FindLast();
	DTS2 = DB->TabValuesLPR->FieldByName("DateTimeStamp")->AsDateTime;
	if(	DTS1 <= DTS2 ) DTS1 = DTS2 + One_mS;

	DB->TabValuesLPR->Append();
	DB->TabValuesLPR->FieldValues["DateTimeStamp"] = DTS1;
	DB->TabValuesLPR->FieldValues["RecNo"] = RecordingNo;
	DB->TabValuesLPR->FieldValues["SensorSerialNo"] = DB->TabSensors->FieldByName("SensorSerialNo")->AsInteger;
	DB->TabValuesLPR->FieldValues["ValueV"] = AnVal1;
	DB->TabValuesLPR->FieldValues["ValueI"] = AnVal2;
	DB->TabValuesLPR->Post();

	DB->TabProject->Edit();
	DB->TabProject->FieldValues["DataVer"] = DB->TabProject->FieldByName("DataVer")->AsInteger + 1;
	DB->TabProject->FieldValues["LastValVer"] = DB->TabProject->FieldByName("LastValVer")->AsInteger + 1;
	DB->TabProject->Post();
	#if DebugNetIntLocal == 1
	Debug("LPR V = " + FloatToStr(AnVal1) + " I = " + FloatToStr(AnVal2) + " On CanAdr " + IntToStr( MessageId ));
  #endif
  break;

  case MSG_TX_CALOFS: ;
  break;

  case MSG_TX_CALGAIN: ;
  break;

  case MSG_TX_HELO: ;
  break;

  case MSG_TX_CAPABILITY:
  CanAdr = MessageId;
  if( DB->TabNodes->Locate( "NodeCanAdr", CanAdr, NoOpts ) )
  {
	DB->TabNodes->Edit();
	DB->TabNodes->FieldValues["NodeType"] = CANInMsg[3];
	DB->TabNodes->FieldValues["NodeStatus"] = 0;
	DB->TabNodes->FieldValues["NodeConnected"] = true;
	DB->TabNodes->Post();
	SerNo = DB->TabNodes->FieldByName("NodeSerialNo")->AsInteger;
	CapReqCounter--;
	if( ( CANInMsg[3] == 10 ) ||
		( CANInMsg[3] == 15 ) ||
		( CANInMsg[3] == 16 ) ||
		( CANInMsg[3] == 17 ) ||
		( CANInMsg[3] == 20 ))
	{
	  if( !DB->TabSensors->Locate( "SensorSerialNo", SerNo, NoOpts ) )
	  {
		DB->TabSensors->Append();
		DB->TabSensors->FieldValues["SensorSerialNo"] = SerNo;
		DB->TabSensors->FieldValues["SensorName"] = IntToStr( SerNo );
		DB->TabSensors->FieldValues["SensorCanAdr"] = CanAdr;
		DB->TabSensors->FieldValues["SensorStatus"] = 0;
		DB->TabSensors->FieldValues["ZoneNo"] = 1;
		DB->TabSensors->FieldValues["SensorType"] = CANInMsg[3];
		DB->TabSensors->FieldValues["RequestStatus"] = -1;
		DB->TabSensors->FieldValues["SensorLPRStep"] = 0;
		DB->TabSensors->FieldValues["SensorAlarmEnabled"] = false;
		DB->TabSensors->FieldValues["SensorAlarmStatus"] = 0;
		DB->TabSensors->FieldValues["SensorLow"] = 0;
		DB->TabSensors->FieldValues["SensorHigh"] = 0;
		DB->TabSensors->FieldValues["SensorGain"] = 1;
		DB->TabSensors->FieldValues["SensorOffset"] = 0;
		DB->TabSensors->FieldValues["SensorUnit"] = "mV";
		DB->TabSensors->FieldValues["SensorConnected"] = true;
		DB->TabSensors->FieldValues["SensorWarmUp"] = 0;
		DB->TabSensors->FieldValues["SensorTemp"] = false;
		DB->TabSensors->FieldValues["SensorVerMajor"] = 0;
		DB->TabSensors->FieldValues["SensorVerMinor"] = 0;

		if( ( CANInMsg[3] == 10 ) ||
			( CANInMsg[3] == 15 ) ||
			( CANInMsg[3] == 20 ))
		{
		  DB->TabSensors->FieldValues["SensorUnit"] = "mV";
		}
		else if (CANInMsg[3] == 16 )
		{
		  DB->TabSensors->FieldValues["SensorUnit"] = "uV";
		}
		else if (CANInMsg[3] == 17 )
		{
		  DB->TabSensors->FieldValues["SensorUnit"] = "ohm";
		}

		DB->TabSensors->Post();
	  }
	  else
	  {
		DB->TabSensors->Edit();
		DB->TabSensors->FieldValues["SensorCanAdr"] = CanAdr;
		DB->TabSensors->FieldValues["SensorType"] = CANInMsg[3];
		DB->TabSensors->FieldValues["SensorStatus"] = 0;
		DB->TabSensors->FieldValues["RequestStatus"] = -1;
		DB->TabSensors->FieldValues["SensorConnected"] = true;
		DB->TabSensors->Post();
	  }
	}
	else if(( CANInMsg[3] == 11 ) || ( CANInMsg[3] == 31 ))
	{
	  if( !DB->TabPowerSupply->Locate( "PSSerialNo", SerNo, NoOpts ) )
	  {
		DB->TabPowerSupply->Append();
		DB->TabPowerSupply->FieldValues["PSSerialNo"] = SerNo;
		DB->TabPowerSupply->FieldValues["PSName"] = IntToStr( SerNo );
		DB->TabPowerSupply->FieldValues["PSCanAdr"] = CanAdr;
		DB->TabPowerSupply->FieldValues["PSStatus"] = 0;
		DB->TabPowerSupply->FieldValues["ZoneNo"] = 1;
		DB->TabPowerSupply->FieldValues["PSType"] = CANInMsg[3];
		DB->TabPowerSupply->FieldValues["RequestStatus"] = -1;
		DB->TabPowerSupply->FieldValues["PSAlarmEnabled"] = False;
		DB->TabPowerSupply->FieldValues["PSAlarmStatusU"] = 0;
		DB->TabPowerSupply->FieldValues["PSAlarmStatusI"] = 0;
		DB->TabPowerSupply->FieldValues["PSLowU"] = 0;
		DB->TabPowerSupply->FieldValues["PSHighU"] = 0;
		DB->TabPowerSupply->FieldValues["PSLowI"] = 0;
		DB->TabPowerSupply->FieldValues["PSHighI"] = 0;
		DB->TabPowerSupply->FieldValues["PSMode"] = 0;
		DB->TabPowerSupply->FieldValues["PSSetVoltage"] = 0;
		DB->TabPowerSupply->FieldValues["PSSetCurrent"] = 0;
		DB->TabPowerSupply->FieldValues["PSOutGain"] = 1;
		DB->TabPowerSupply->FieldValues["PSOutOffset"] = 0;
		DB->TabPowerSupply->FieldValues["PSVOutEnabled"] = false;
		DB->TabPowerSupply->FieldValues["PSRemote"] = false;
		DB->TabPowerSupply->FieldValues["PSConnected"] = true;
		DB->TabPowerSupply->FieldValues["Ch1Gain"] = 1;
		DB->TabPowerSupply->FieldValues["Ch1Offset"] = 0;
		DB->TabPowerSupply->FieldValues["Ch1Unit"] = "V";
		DB->TabPowerSupply->FieldValues["Ch2Gain"] = 1;
		DB->TabPowerSupply->FieldValues["Ch2Offset"] = 0;
		DB->TabPowerSupply->FieldValues["Ch2Unit"] = "A";
		DB->TabPowerSupply->FieldValues["Ch3Gain"] = 1;
		DB->TabPowerSupply->FieldValues["Ch3Offset"] = 0;
		DB->TabPowerSupply->FieldValues["Ch4Gain"] = 1;
		DB->TabPowerSupply->FieldValues["Ch4Offset"] = 0;
		DB->TabPowerSupply->FieldValues["Ch1BitVal"] = 5.0/32767;
		DB->TabPowerSupply->FieldValues["Ch2BitVal"] = 5.0/32767;
		DB->TabPowerSupply->FieldValues["Ch3BitVal"] = 5.0/32767;
		DB->TabPowerSupply->FieldValues["Ch4BitVal"] = 5.0/32767;
		DB->TabPowerSupply->FieldValues["PSVerMajor"] = 0;
		DB->TabPowerSupply->FieldValues["PSVerMinor"] = 0;

		if( CANInMsg[3] == 11 )
		{
			DB->TabPowerSupply->FieldValues["Ch3Unit"] = "?";
			DB->TabPowerSupply->FieldValues["Ch4Unit"] = "?";
		}
		else
		{
			DB->TabPowerSupply->FieldValues["Ch3Unit"] = "V";
			DB->TabPowerSupply->FieldValues["Ch4Unit"] = "V";
        }

        DB->TabPowerSupply->Post();
      }
      else
      {
        DB->TabPowerSupply->Edit();
        DB->TabPowerSupply->FieldValues["PSCanAdr"] = CanAdr;
				DB->TabPowerSupply->FieldValues["PSType"] = CANInMsg[3];
        DB->TabPowerSupply->FieldValues["PSStatus"] = 0;
        DB->TabPowerSupply->FieldValues["RequestStatus"] = -1;
        DB->TabPowerSupply->FieldValues["PSConnected"] = true;
        DB->TabPowerSupply->Post();
      }
    }
  }
	#if DebugNetIntLocal == 1
  Debug( "Capability Sensor at CanAdr "+IntToStr( CanAdr ) + " = " + IntToStr( CANInMsg[3]) );
  #endif
  if( CapReqCounter == 0 )
  {
		TimerSetCANGroup->Enabled = true;
		TimerIShuntReq->Enabled = true;
		TimerVerReq->Enabled = true;
  }
  break;

  case MSG_TX_EEDATA: ;
  break;

  case MSG_TX_ADREGDATA: ;
  break;

  case MSG_TX_IRRESULT: ;
  break;

  case MSG_TX_LPREND:
  CanAdr = MessageId;
  if( DB->TabSensors->Locate( "SensorCanAdr", CanAdr, NoOpts ))
    {
    DB->TabSensors->Edit();
    DB->TabSensors->FieldValues["RequestStatus"] = 0;
    DB->TabSensors->Post();

	ZoneNo = DB->TabSensors->FieldByName("ZoneNo")->AsInteger;
    SendClrLPR( CanAdr );
	WatchLPRStatus( ZoneNo );
	}
  break;

  case MSG_TX_SHUNTVALUE: ;
	CanAdr = MessageId;
	if( DB->TabSensors->Locate( "SensorCanAdr", CanAdr, NoOpts ))
	{
		IShunt = CANInMsg[3]+CANInMsg[4]*256;
		if( IShunt > 64000 ) IShunt = 100000 + ( IShunt - 65000 ) * 10;

		if( DB->TabNodes->FieldByName("NodeType")->AsInteger == 10 ) IShunt = IShunt / 10;
		else if( DB->TabNodes->FieldByName("NodeType")->AsInteger == 16 )
		{
		  IShunt = CANInMsg[5];
		  IShunt = IShunt * 200 /32767;
		}
		else if( DB->TabNodes->FieldByName("NodeType")->AsInteger == 20 ) IShunt = IShunt / 100;

		DB->TabSensors->Edit();
		DB->TabSensors->FieldValues["SensorIShunt"] = IShunt;
		DB->TabSensors->Post();
		#if DebugNetIntLocal == 1
		Debug( "IShunt CanAdr "+IntToStr( CanAdr ) + " = " + FloatToStr(IShunt) );
		#endif
	}
	else if( DB->TabPowerSupply->Locate( "PSCanAdr", CanAdr, NoOpts ))
	{
		if( DB->TabPowerSupply->FieldByName("PSType")->AsInteger == 11 )
		{
			DB->TabPowerSupply->Edit();
			DB->TabPowerSupply->FieldValues["Ch1BitVal"] = CANInMsg[3] * 0.2 /65535;
			DB->TabPowerSupply->FieldValues["Ch2BitVal"] = CANInMsg[4] * 0.2 /65535;
			DB->TabPowerSupply->FieldValues["Ch3BitVal"] = CANInMsg[5] * 0.2 /65535;
			DB->TabPowerSupply->FieldValues["Ch4BitVal"] = CANInMsg[6] * 0.2 /65535;
			DB->TabPowerSupply->Post();
		}
		else
		{
			DB->TabPowerSupply->Edit();
			DB->TabPowerSupply->FieldValues["Ch1BitVal"] = CANInMsg[3] * 0.2 /32767;
			DB->TabPowerSupply->FieldValues["Ch2BitVal"] = CANInMsg[4] * 0.2 /32767;
			DB->TabPowerSupply->FieldValues["Ch3BitVal"] = CANInMsg[5] * 0.2 /32767;
			DB->TabPowerSupply->FieldValues["Ch4BitVal"] = CANInMsg[6] * 0.2 /32767;
			DB->TabPowerSupply->Post();
		}

		#if DebugNetIntLocal == 1
		Debug( "BitVal CanAdr " +
					 IntToStr( CanAdr ) +
					 " = " + IntToStr( CANInMsg[3]) +
					 ", " + IntToStr( CANInMsg[4]) +
					 ", " + IntToStr( CANInMsg[5]) +
					 ", " + IntToStr( CANInMsg[6]) );
		#endif

	}
  break;

  case MSG_TX_SAMPLE: // Reqest Sample ( Monitor, LastValue or Decay )
  Tag = CANInMsg[3];
  if( DB->TabNodes->Locate("NodeCanAdr", MessageId, NoOpts) )
	{
	  if(( DB->TabNodes->FieldByName("NodeType")->AsInteger == 10 ) ||
		   ( DB->TabNodes->FieldByName("NodeType")->AsInteger == 15 ) ||
		   ( DB->TabNodes->FieldByName("NodeType")->AsInteger == 16 ) ||
		   ( DB->TabNodes->FieldByName("NodeType")->AsInteger == 17 ) ||
		   ( DB->TabNodes->FieldByName("NodeType")->AsInteger == 20 ))
	  {
		if( DB->TabSensors->Locate("SensorCanAdr", MessageId, NoOpts) )
		{
		  ZoneNo = DB->TabSensors->FieldByName("ZoneNo")->AsInteger;
		  DB->TabZones->Locate("ZoneNo", ZoneNo, NoOpts );
		  RecType = DB->TabZones->FieldByName("RecType")->AsInteger;
		  RecordingNo = DB->TabZones->FieldByName("RecNo")->AsInteger;

		  if(( DB->TabNodes->FieldByName("NodeType")->AsInteger == 10 ) ||
			   ( DB->TabNodes->FieldByName("NodeType")->AsInteger == 15 ) ||
			   ( DB->TabNodes->FieldByName("NodeType")->AsInteger == 20 ))
		  {
			ADVal1 = CANInMsg[4]+CANInMsg[5]*256;
			AnVal1 = ADVal1; AnVal1 = AnVal1 * 1000 * 5 / 65535;

			if( DB->TabSensors->FieldByName("SensorTemp")->AsBoolean == true )
			{
			  ADVal2 = CANInMsg[6]+CANInMsg[7]*256;
			  if(( ADVal2 & 512 ) == 512 ) ADVal2 = - ((( ~ADVal2 ) & 511 ) + 1 );
			  AnVal2 = ADVal2; AnVal2 = AnVal2 / 4;
			}

		  }
		  else if( DB->TabNodes->FieldByName("NodeType")->AsInteger == 16 )
		  {
			ADVal1 = CANInMsg[4]+CANInMsg[5]*256;
			AnVal1 = ADVal1; AnVal1 = AnVal1 * DB->TabSensors->FieldByName("SensorIShunt")->AsFloat;
		  }
		  else if( DB->TabNodes->FieldByName("NodeType")->AsInteger == 17 )
		  {
			// Camur II R  [cmd][can][can][count][kvot][kvot][range]

			switch( CANInMsg[6] )
			{
			  case 0: IShunt = DB->TabSensors->FieldByName("SensorIShunt")->AsFloat; break;
			  case 1: IShunt = DB->TabSensors->FieldByName("SensorIShunt1")->AsFloat;break;
			  case 2: IShunt = DB->TabSensors->FieldByName("SensorIShunt2")->AsFloat; break;
			  case 3: IShunt = DB->TabSensors->FieldByName("SensorIShunt3")->AsFloat; break;
			}
			UADVal1 = CANInMsg[4]+CANInMsg[5]*256;
			AnVal1 = UADVal1; AnVal1 = AnVal1 * IShunt / 10000;

		  }
		  else
		  {
			ADVal = CANInMsg[4]+CANInMsg[5]*256;
			AnVal1 = ADVal; AnVal1 = AnVal1 * 1000 * 5 / 65535;
			ADVal1 = ADVal;
		  }

		  AnVal1_Scl = AnVal1 * DB->TabSensors->FieldByName("SensorGain")->AsFloat +
								DB->TabSensors->FieldByName("SensorOffset")->AsFloat;
		  DB->TabSensors->Edit();
		  DB->TabSensors->FieldValues["SensorLastValue"] = AnVal1_Scl;

		  if( DB->TabSensors->FieldByName("SensorTemp")->AsBoolean == true  &&
			  DB->TabNodes->FieldByName("NodeType")->AsInteger != 17 )
		  {
			DB->TabSensors->FieldValues["SensorLastTemp"] = AnVal2;
		  }
		  DB->TabSensors->Post();

		  DB->TabProject->Edit();
		  DB->TabProject->FieldValues["LastValVer"] = DB->TabProject->FieldByName("LastValVer")->AsInteger + 1;
		  DB->TabProject->Post();

		  #if DebugNetIntLocal == 1
				  Debug("Incoming A/D on CanAdr " + IntToStr( MessageId ) + " = " + IntToStr(ADVal1));
		  #endif

		  if( Tag == DB->TabSensors->FieldByName("RequestStatus")->AsInteger )
		  {
			if( RecType == 1 )
			{

			  // If time has been set back store value last in tab.
			  DTS1 = Now();
			  DB->TabValues->FindLast();
			  DTS2 = DB->TabValues->FieldByName("DateTimeStamp")->AsDateTime;
			  if(	DTS1 <= DTS2 ) DTS1 = DTS2 + One_mS;

			  DB->TabValues->Append();
			  DB->TabValues->FieldValues["RecNo"] = RecordingNo;
			  DB->TabValues->FieldValues["SensorSerialNo"] = DB->TabSensors->FieldByName("SensorSerialNo")->AsInteger;
			  DB->TabValues->FieldValues["DateTimeStamp"] = DTS1;

			  if (DB->TabNodes->FieldByName("NodeType")->AsInteger == 17) DB->TabValues->FieldValues["ValueType"] = "R";
			  else DB->TabValues->FieldValues["ValueType"] = "U";

			  DB->TabValues->FieldValues["ValueUnit"] = DB->TabSensors->FieldByName("SensorUnit")->AsString;
			  DB->TabValues->FieldValues["RawValue"] = AnVal1;
			  DB->TabValues->FieldValues["Value"] = AnVal1_Scl;
			  DB->TabValues->Post();

			  if( DB->TabSensors->FieldByName("SensorTemp")->AsBoolean == true &&
				  DB->TabNodes->FieldByName("NodeType")->AsInteger != 17 )
			  {
				DB->TabValues->Append();
				DB->TabValues->FieldValues["RecNo"] = RecordingNo;
				DB->TabValues->FieldValues["SensorSerialNo"] = DB->TabSensors->FieldByName("SensorSerialNo")->AsInteger;
				DB->TabValues->FieldValues["DateTimeStamp"] = DTS1;
				DB->TabValues->FieldValues["ValueType"] = "T";
				DB->TabValues->FieldValues["ValueUnit"] = "C";
				DB->TabValues->FieldValues["RawValue"] = AnVal2;
				DB->TabValues->FieldValues["Value"] = AnVal2;
				DB->TabValues->Post();
			  }

			  //AlarmCheck ( on scaled value )

			  if( DB->TabSensors->FieldByName("SensorAlarmEnabled")->AsBoolean == true )
			  {
				StatusChanged = false;
				LowLev1 = DB->TabSensors->FieldByName("SensorLow")->AsFloat;
				HighLev1 = DB->TabSensors->FieldByName("SensorHigh")->AsFloat;
				AlarmStatus1 = DB->TabSensors->FieldByName("SensorAlarmStatus")->AsInteger;

				if( ( AnVal1_Scl < LowLev1 ) && ( AlarmStatus1 == 0 ) )
				{
				  AlarmStatus1 = 1;
				  StatusChanged = true;
				  DB->Log( LevAlarm, SensorLow, High,
				  DB->TabSensors->FieldByName("SensorName")->AsString,
				  DB->TabSensors->FieldByName("SensorSerialNo")->AsInteger, ADVal1 );
				}
				else if( ( AnVal1_Scl > HighLev1 ) && ( AlarmStatus1 == 0 ) )
				{
				  AlarmStatus1 = 1;
				  StatusChanged = true;
				  DB->Log( LevAlarm, SensorHigh, High,
				  DB->TabSensors->FieldByName("SensorName")->AsString,
				  DB->TabSensors->FieldByName("SensorSerialNo")->AsInteger, ADVal1 );
				}
				else if( ( AnVal1_Scl > LowLev1 ) && ( AnVal1_Scl < HighLev1 ) && ( AlarmStatus1 == 1 ) )
				{
				  AlarmStatus1 = 0;
				  StatusChanged = true;
				  DB->Log( LevAlarm, SensorNormal, High,
				  DB->TabSensors->FieldByName("SensorName")->AsString,
				  DB->TabSensors->FieldByName("SensorSerialNo")->AsInteger, ADVal1 );
				}

				if( StatusChanged == true )
				{
				  DB->TabSensors->Edit();
				  DB->TabSensors->FieldValues["SensorAlarmStatus"] = AlarmStatus1;
				  DB->TabSensors->Post();
				  TimerUpdateAlarm->Enabled = true;
				}
			  } // AlarmCheck
			}
			else if( RecType == 3 )
			{
			  // If time has been set back store value last in tab.
			  DTS1 = Now();
			  DB->TabValuesDecay->FindLast();
			  DTS2 = DB->TabValuesDecay->FieldByName("DateTimeStamp")->AsDateTime;
			  if(	DTS1 <= DTS2 ) DTS1 = DTS2 + One_mS;


			  DB->TabValuesDecay->Append();
			  DB->TabValuesDecay->FieldValues["RecNo"] = RecordingNo;
			  DB->TabValuesDecay->FieldValues["SensorSerialNo"] = DB->TabSensors->FieldByName("SensorSerialNo")->AsInteger;
			  DB->TabValuesDecay->FieldValues["DateTimeStamp"] = DTS1;
			  DB->TabValuesDecay->FieldValues["Value"] = AnVal1_Scl;
			  DB->TabValuesDecay->Post();
			}
			DB->TabSensors->Edit();
			DB->TabSensors->FieldValues["RequestStatus"] =  -Tag;
			DB->TabSensors->Post();

			DB->TabProject->Edit();
					  DB->TabProject->FieldValues["DataVer"] = DB->TabProject->FieldByName("DataVer")->AsInteger + 1;
			DB->TabProject->Post();

		  }  // if( request status match
		}  // if( locate tab sensor
	  }  // if(  sensor
	  else if(( DB->TabNodes->FieldByName("NodeType")->AsInteger == 11 ) ||
					  ( DB->TabNodes->FieldByName("NodeType")->AsInteger == 31 ))
	  {  // powersuply
		if( DB->TabPowerSupply->Locate("PSCanAdr", MessageId, NoOpts) )
		{
		  ZoneNo = DB->TabPowerSupply->FieldByName("ZoneNo")->AsInteger;
		  DB->TabZones->Locate("ZoneNo", ZoneNo, NoOpts );
		  RecType = DB->TabZones->FieldByName("RecType")->AsInteger;
		  RecordingNo = DB->TabZones->FieldByName("RecNo")->AsInteger;

		  UADVal1 = CANInMsg[4]+CANInMsg[5]*256;
		  UADVal2 = CANInMsg[6]+CANInMsg[7]*256;
		  AnVal1 = UADVal1; AnVal1 = AnVal1 * DB->TabPowerSupply->FieldByName("Ch1BitVal")->AsFloat;
		  AnVal2 = UADVal2; AnVal2 = AnVal2 * DB->TabPowerSupply->FieldByName("Ch2BitVal")->AsFloat;
		  AnVal1_Scl = AnVal1 * DB->TabPowerSupply->FieldByName("Ch1Gain")->AsFloat +
		  DB->TabPowerSupply->FieldByName("Ch1Offset")->AsFloat;
		  AnVal2_Scl = AnVal2 * DB->TabPowerSupply->FieldByName("Ch2Gain")->AsFloat +
		  DB->TabPowerSupply->FieldByName("Ch2Offset")->AsFloat;

		  DB->TabPowerSupply->Edit();
		  DB->TabPowerSupply->FieldValues["PSLastValueU"] = AnVal1_Scl;
		  DB->TabPowerSupply->FieldValues["PSLastValueI"] = AnVal2_Scl;
		  DB->TabPowerSupply->Post();

		  DB->TabProject->Edit();
		  DB->TabProject->FieldValues["LastValVer"] = DB->TabProject->FieldByName("LastValVer")->AsInteger + 1;
		  DB->TabProject->Post();

		  if( Tag == DB->TabPowerSupply->FieldByName("RequestStatus")->AsInteger )
		  { // request status match
			if( RecType == 1 )
			{
			  // If time has been set back store value last in tab.
			  DTS1 = Now();
			  DB->TabValues->FindLast();
			  DTS2 = DB->TabValues->FieldByName("DateTimeStamp")->AsDateTime;
			  if(	DTS1 <= DTS2 ) DTS1 = DTS2 + One_mS;

			  DB->TabValues->Append();
			  DB->TabValues->FieldValues["RecNo"] = RecordingNo;
			  DB->TabValues->FieldValues["SensorSerialNo"] = DB->TabPowerSupply->FieldByName("PSSerialNo")->AsInteger;
			  DB->TabValues->FieldValues["DateTimeStamp"] = DTS1;
			  DB->TabValues->FieldValues["ValueType"] = "PSU";
			  DB->TabValues->FieldValues["ValueUnit"] = "V";
			  DB->TabValues->FieldValues["RawValue"] = AnVal1;
			  DB->TabValues->FieldValues["Value"] = AnVal1_Scl;
			  DB->TabValues->Post();

			  DB->TabValues->Append();
			  DB->TabValues->FieldValues["RecNo"] = RecordingNo;
			  DB->TabValues->FieldValues["SensorSerialNo"] = DB->TabPowerSupply->FieldByName("PSSerialNo")->AsInteger;
			  DB->TabValues->FieldValues["DateTimeStamp"] = DTS1;
			  DB->TabValues->FieldValues["ValueType"] = "PSI";
			  DB->TabValues->FieldValues["ValueUnit"] = "A";
			  DB->TabValues->FieldValues["RawValue"] = AnVal2;
			  DB->TabValues->FieldValues["Value"] = AnVal2_Scl;
			  DB->TabValues->Post();

			  //AlarmCheck

			  AlarmStatus1 = DB->TabPowerSupply->FieldByName("PSAlarmStatusU")->AsInteger;
			  AlarmStatus2 = DB->TabPowerSupply->FieldByName("PSAlarmStatusI")->AsInteger;
			  StatusChanged = false;

			  if( DB->TabPowerSupply->FieldByName("PSAlarmEnabled")->AsBoolean == true )
			  {
				LowLev1 = DB->TabPowerSupply->FieldByName("PSLowU")->AsFloat;
				HighLev1 = DB->TabPowerSupply->FieldByName("PSHighU")->AsFloat;
				LowLev2 = DB->TabPowerSupply->FieldByName("PSLowI")->AsFloat;
				HighLev2 = DB->TabPowerSupply->FieldByName("PSHighI")->AsFloat;

				if( ( AnVal1_Scl < LowLev1 ) && ( AlarmStatus1 == 0 ) )
				{
				  AlarmStatus1 = 1;
				  StatusChanged = true;
				  DB->Log( LevAlarm, PSLowU, High,
				  DB->TabPowerSupply->FieldByName("PSName")->AsString,
				  DB->TabPowerSupply->FieldByName("PSSerialNo")->AsInteger, UADVal1 );
				}
				else if( ( AnVal1_Scl > HighLev1 ) && ( AlarmStatus1 == 0 ) )
				{
				  AlarmStatus1 = 1;
				  StatusChanged = true;
				  DB->Log( LevAlarm, PSHighU, High,
				  DB->TabPowerSupply->FieldByName("PSName")->AsString,
				  DB->TabPowerSupply->FieldByName("PSSerialNo")->AsInteger, UADVal1 );
				}
				else if( ( AnVal1_Scl > LowLev1 ) && ( AnVal1_Scl < HighLev1 ) && ( AlarmStatus1 == 1 ) )
				{
				  AlarmStatus1 = 0;
				  StatusChanged = true;
				  DB->Log( LevAlarm, PSNormalU, High,
				  DB->TabPowerSupply->FieldByName("PSName")->AsString,
				  DB->TabPowerSupply->FieldByName("PSSerialNo")->AsInteger, UADVal1 );
				}

				if( ( AnVal2_Scl < LowLev2 ) && ( AlarmStatus2 == 0 ) )
				{
				  AlarmStatus2 = 1;
				  StatusChanged = true;
				  DB->Log( LevAlarm, PSLowI, High,
				  DB->TabPowerSupply->FieldByName("PSName")->AsString,
				  DB->TabPowerSupply->FieldByName("PSSerialNo")->AsInteger, UADVal2 );
				}
				else if( ( AnVal2_Scl > HighLev2 ) && ( AlarmStatus2 == 0 ) )
				{
				  AlarmStatus2 = 1;
				  StatusChanged = true;
				  DB->Log( LevAlarm, PSHighI, High,
				  DB->TabPowerSupply->FieldByName("PSName")->AsString,
				  DB->TabPowerSupply->FieldByName("PSSerialNo")->AsInteger, UADVal2 );
				}
				else if( ( AnVal2_Scl > LowLev2 ) && ( AnVal2_Scl < HighLev2 ) && ( AlarmStatus2 == 1 ) )
				{
				  AlarmStatus2 = 0;
				  StatusChanged = true;
				  DB->Log( LevAlarm, PSNormalI, High,
				  DB->TabPowerSupply->FieldByName("PSName")->AsString,
				  DB->TabPowerSupply->FieldByName("PSSerialNo")->AsInteger, UADVal2 );
				}

			  } // AlarmCheck
			  else // PSAlarmEnabled == false
			  {
				if( AlarmStatus1 != 0 )
				{
				  AlarmStatus1 = 0;
				  StatusChanged = true;
				}
				if( AlarmStatus2 != 0 )
				{
				  AlarmStatus2 = 0;
				  StatusChanged = true;
				}
			  }

			  if( StatusChanged == true )
			  {
				DB->TabPowerSupply->Edit();
				DB->TabPowerSupply->FieldValues["PSAlarmStatusU"] = AlarmStatus1;
				DB->TabPowerSupply->FieldValues["PSAlarmStatusI"] = AlarmStatus2;
				DB->TabPowerSupply->Post();
				TimerUpdateAlarm->Enabled = true;
			  }

			} //if( RecType == 1 )

			else if( RecType == 3 )
			{
			  // If time has been set back store value last in tab.
			  DTS1 = Now();
			  DB->TabValuesDecay->FindLast();
			  DTS2 = DB->TabValuesDecay->FieldByName("DateTimeStamp")->AsDateTime;
			  if(	DTS1 <= DTS2 ) DTS1 = DTS2 + One_mS;

			  DB->TabValuesDecay->Append();
			  DB->TabValuesDecay->FieldValues["RecNo"] = RecordingNo;
			  DB->TabValuesDecay->FieldValues["SensorSerialNo"] = DB->TabPowerSupply->FieldByName("PSSerialNo")->AsInteger;
			  DB->TabValuesDecay->FieldValues["DateTimeStamp"] = DTS1;
			  DB->TabValuesDecay->FieldValues["Value"] = AnVal1_Scl;
			  DB->TabValuesDecay->Post();
			}

			DB->TabPowerSupply->Edit();
			DB->TabPowerSupply->FieldValues["RequestStatus"] = -Tag;
			DB->TabPowerSupply->Post();

			DB->TabProject->Edit();
			DB->TabProject->FieldValues["DataVer"] = DB->TabProject->FieldByName("DataVer")->AsInteger + 1;
			DB->TabProject->Post();

		  } // if( request stus match
		}  // if( locate tab powersupply
	  }  // if( powersupply
	  //Debug("Incoming A/D on CanAdr " + IntToStr( MessageId ) + " = " + IntToStr(ADVal1));
  }
  else
  {
	#if DebugNetIntLocal == 1
	Debug("Incoming A/D on undefined CanAdr " + IntToStr( MessageId ));
	#endif
  }
  break;

  case MSG_TX_SAMPLEEXTCH: // Reqest extended Sample ( Monitor, LastValue or Decay )
  Tag = CANInMsg[3];
  if( DB->TabNodes->Locate("NodeCanAdr", MessageId, NoOpts) )
  {
	if(( DB->TabNodes->FieldByName("NodeType")->AsInteger == 11 ) ||
	   ( DB->TabNodes->FieldByName("NodeType")->AsInteger == 31 ))
	{  // powersuply
	  if( DB->TabPowerSupply->Locate("PSCanAdr", MessageId, NoOpts) )
	  {
		ZoneNo = DB->TabPowerSupply->FieldByName("ZoneNo")->AsInteger;
		DB->TabZones->Locate("ZoneNo", ZoneNo, NoOpts );
		RecType = DB->TabZones->FieldByName("RecType")->AsInteger;
		RecordingNo = DB->TabZones->FieldByName("RecNo")->AsInteger;

		UADVal1 = CANInMsg[4]+CANInMsg[5]*256;
		UADVal2 = CANInMsg[6]+CANInMsg[7]*256;
		AnVal1 = UADVal1; AnVal1 = AnVal1 * DB->TabPowerSupply->FieldByName("Ch3BitVal")->AsFloat;
		AnVal2 = UADVal2; AnVal2 = AnVal2 * DB->TabPowerSupply->FieldByName("Ch4BitVal")->AsFloat;
		AnVal1_Scl = AnVal1 * DB->TabPowerSupply->FieldByName("Ch3Gain")->AsFloat +
		DB->TabPowerSupply->FieldByName("Ch3Offset")->AsFloat;
		AnVal2_Scl = AnVal2 * DB->TabPowerSupply->FieldByName("Ch4Gain")->AsFloat +
		DB->TabPowerSupply->FieldByName("Ch4Offset")->AsFloat;

        DB->TabPowerSupply->Edit();
		DB->TabPowerSupply->FieldValues["PSLastValueCh3"] = AnVal1_Scl;
        DB->TabPowerSupply->FieldValues["PSLastValueCh4"] = AnVal2_Scl;
        DB->TabPowerSupply->Post();

        DB->TabProject->Edit();
		DB->TabProject->FieldValues["LastValVer"] = DB->TabProject->FieldByName("LastValVer")->AsInteger + 1;
        DB->TabProject->Post();


		if( Tag  == - DB->TabPowerSupply->FieldByName("RequestStatus")->AsInteger )
        { // request status match
          if( RecType == 1 )
					{
			// If time has been set back store value last in tab.
			DTS1 = Now();
			DB->TabValues->FindLast();
			DTS2 = DB->TabValues->FieldByName("DateTimeStamp")->AsDateTime;
			if(	DTS1 <= DTS2 ) DTS1 = DTS2 + One_mS;

            DB->TabValues->Append();
			DB->TabValues->FieldValues["RecNo"] = RecordingNo;
			DB->TabValues->FieldValues["SensorSerialNo"] = DB->TabPowerSupply->FieldByName("PSSerialNo")->AsInteger;
			DB->TabValues->FieldValues["DateTimeStamp"] = DTS1;
            DB->TabValues->FieldValues["ValueType"] = "PS3";
			DB->TabValues->FieldValues["ValueUnit"] = DB->TabPowerSupply->FieldByName("Ch3Unit")->AsString;
            DB->TabValues->FieldValues["RawValue"] = AnVal1;
            DB->TabValues->FieldValues["Value"] = AnVal1_Scl;
            DB->TabValues->Post();

            DB->TabValues->Append();
			DB->TabValues->FieldValues["RecNo"] = RecordingNo;
			DB->TabValues->FieldValues["SensorSerialNo"] = DB->TabPowerSupply->FieldByName("PSSerialNo")->AsInteger;
			DB->TabValues->FieldValues["DateTimeStamp"] = DTS1;
            DB->TabValues->FieldValues["ValueType"] = "PS4";
			DB->TabValues->FieldValues["ValueUnit"] = DB->TabPowerSupply->FieldByName("Ch4Unit")->AsString;
            DB->TabValues->FieldValues["RawValue"] = AnVal2;
            DB->TabValues->FieldValues["Value"] = AnVal2_Scl;
            DB->TabValues->Post();
          }
        }
	  }
	}  // powersuply
	if( DB->TabNodes->FieldByName("NodeType")->AsInteger == 17 )
	{  // sensors
	  if( DB->TabSensors->Locate("SensorCanAdr", MessageId, NoOpts) )
	  {
		ZoneNo = DB->TabSensors->FieldByName("ZoneNo")->AsInteger;
		DB->TabZones->Locate("ZoneNo", ZoneNo, NoOpts );
		RecType = DB->TabZones->FieldByName("RecType")->AsInteger;
		RecordingNo = DB->TabZones->FieldByName("RecNo")->AsInteger;

		UADVal1 = CANInMsg[4]+CANInMsg[5]*256;

		ADVal2 = CANInMsg[4]+CANInMsg[5]*256;
		if(( ADVal2 & 512 ) == 512 ) ADVal2 = - ((( ~ADVal2 ) & 511 ) + 1 );
		AnVal2 = ADVal2; AnVal2 = AnVal2 / 4;

		DB->TabSensors->Edit();
		DB->TabSensors->FieldValues["SensorLastTemp"] = AnVal2;
		DB->TabSensors->Post();

        DB->TabProject->Edit();
		DB->TabProject->FieldValues["LastValVer"] = DB->TabProject->FieldByName("LastValVer")->AsInteger + 1;
        DB->TabProject->Post();


		if( Tag  == - DB->TabSensors->FieldByName("RequestStatus")->AsInteger )
        { // request status match
          if( RecType == 1 )
		  {
			// If time has been set back store value last in tab.
			DTS1 = Now();
			DB->TabValues->FindLast();
			DTS2 = DB->TabValues->FieldByName("DateTimeStamp")->AsDateTime;
			if(	DTS1 <= DTS2 ) DTS1 = DTS2 + One_mS;

			if( DB->TabSensors->FieldByName("SensorTemp")->AsBoolean == true  )
			{
			  DB->TabValues->Append();
			  DB->TabValues->FieldValues["RecNo"] = RecordingNo;
			  DB->TabValues->FieldValues["SensorSerialNo"] = DB->TabSensors->FieldByName("SensorSerialNo")->AsInteger;
			  DB->TabValues->FieldValues["DateTimeStamp"] = DTS1;
			  DB->TabValues->FieldValues["ValueType"] = "T";
			  DB->TabValues->FieldValues["ValueUnit"] = "C";
			  DB->TabValues->FieldValues["RawValue"] = AnVal2;
			  DB->TabValues->FieldValues["Value"] = AnVal2;
			  DB->TabValues->Post();
			}
          }
        }
	  }
	}  // R-node
  }
  else
  {
    #if DebugNetIntLocal == 1
    Debug("Incoming A/D on undefined CanAdr " + IntToStr( MessageId ));
    #endif
  }
  break;

  case MSG_TX_VERSION:
  CanAdr = MessageId;
	if( DB->TabSensors->Locate( "SensorCanAdr", CanAdr, NoOpts ))
  {
		DB->TabSensors->Edit();
		DB->TabSensors->FieldValues["SensorVerMajor"] = CANInMsg[3];
		DB->TabSensors->FieldValues["SensorVerMinor"] = CANInMsg[4];
		DB->TabSensors->Post();
		#if DebugNetIntLocal == 1
		Debug( "Version CanAdr "+IntToStr( CanAdr ) + " = " + IntToStr( CANInMsg[3]) + "." + IntToStr(CANInMsg[4]) );
		#endif
  }
	else if( DB->TabPowerSupply->Locate( "PSCanAdr", CanAdr, NoOpts ))
  {
	DB->TabPowerSupply->Edit();
		DB->TabPowerSupply->FieldValues["PSVerMajor"] = CANInMsg[3];
		DB->TabPowerSupply->FieldValues["PSVerMinor"] = CANInMsg[4];
		DB->TabPowerSupply->Post();
		#if DebugNetIntLocal == 1
		Debug( "Version CanAdr "+IntToStr( CanAdr ) + " = " + IntToStr( CANInMsg[3]) + "." + IntToStr(CANInMsg[4]) );
	#endif
	}
  break;

  case MSG_TX_SHUNTS:

  ADVal1 = CANInMsg[4]+CANInMsg[5]*256;
  ADVal2 = CANInMsg[6];if( ADVal2 > 127 ) ADVal2 = ADVal2 - 256;
  AnVal1 = ADVal1; AnVal1 = AnVal1 * pow(10,ADVal2);
  CanAdr = MessageId;
	if( DB->TabSensors->Locate( "SensorCanAdr", CanAdr, NoOpts ))
	{
	  DB->TabSensors->Edit();
	  switch (CANInMsg[3])
	  {
		case 0: DB->TabSensors->FieldValues["SensorIShunt"]  = AnVal1; break;
		case 1: DB->TabSensors->FieldValues["SensorIShunt1"] = AnVal1; break;
		case 2: DB->TabSensors->FieldValues["SensorIShunt2"] = AnVal1; break;
		case 3: DB->TabSensors->FieldValues["SensorIShunt3"] = AnVal1; break;
	  }
	  DB->TabSensors->Post();

	  #if DebugNetIntLocal == 1
			  Debug("Incoming IShunt" + IntToStr( CANInMsg[3] ) + " = " + FloatToStr(AnVal1) + " on CanAdr " + IntToStr(CanAdr));
	  #endif

	}
  break;


	case MSG_TX_UNHANDLED:
  #if DebugNetIntLocal == 1
  Debug("Unhandled command #" + IntToStr(CANInMsg[3]));
  #endif
  break;

  default: ;
}

}

//---------------------------------------------------------------------------

Word __fastcall TCIISNetInterface::GetCanAdr()
{
Word CanAdr;

DB->TabControllers->Locate( "CtrlName", Ctrl, NoOpts );
CanAdr = DB->TabControllers->FieldByName("NextCanAdr")->AsInteger;
DB->TabControllers->Edit();
DB->TabControllers->FieldValues["NextCanAdr"] = CanAdr + 1;
DB->TabControllers->Post();
return CanAdr;
}
//---------------------------------------------------------------------------

bool __fastcall TCIISNetInterface::Connected()
{
  return CIINetConnected;
}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::Debug(String Message)
{
  if( DW != NULL ) DW->Log(Message);
}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::TimerUpdateAlarmsEvent(TObject *Sender)
{
int  ZoneNo;

	TimerUpdateAlarm->Enabled = false;
	if( DB->TabZones->FindFirst() )
	{
		do
		{
		ZoneNo = DB->TabZones->FieldByName("ZoneNo")->AsInteger;
			if( ZoneNo > 1 )
			{ // for ZoneNo <> 1
				DB->TabSensors->Filter = "[ZoneNo] = " + IntToStr( ZoneNo ) +
																" AND [SensorAlarmStatus] = 1";
				DB->TabSensors->Filtered = true;
				DB->TabPowerSupply->Filter = "[ZoneNo] = " + IntToStr( ZoneNo ) +
																	" AND ([PSAlarmStatusU] = 1 OR [PSAlarmStatusI] = 1)";
				DB->TabPowerSupply->Filtered = true;

				if( DB->TabSensors->FindFirst() || DB->TabPowerSupply->FindFirst() )
				{
					DB->TabZones->Edit();
					DB->TabZones->FieldValues["ZoneAlarmStatus"] = 1;
					DB->TabZones->Post();
				}
				else
				{
					DB->TabZones->Edit();
					DB->TabZones->FieldValues["ZoneAlarmStatus"] = 0;
					DB->TabZones->Post();
				}
			// for ZoneNo <> 1
			DB->TabSensors->Filter = "";
			DB->TabSensors->Filtered = false;
			DB->TabSensors->Refresh();
			DB->TabPowerSupply->Filter = "";
			DB->TabPowerSupply->Filtered = false;
			DB->TabPowerSupply->Refresh();
			}
		}
		while( DB->TabZones->FindNext() == true);
	}

	if( DB->TabControllers->FindFirst() )
	{
		do
		{
			DB->TabZones->Filter = "[ZoneAlarmStatus] = 1";
			DB->TabZones->Filtered = true;
			if( DB->TabZones->FindFirst() )
			{
				DB->TabControllers->Edit();
				DB->TabControllers->FieldValues["CtrlAlarmStatus"] = 1;
				DB->TabControllers->Post();
			}
			else
			{
				DB->TabControllers->Edit();
				DB->TabControllers->FieldValues["CtrlAlarmStatus"] = 0;
				DB->TabControllers->Post();
			}
			DB->TabZones->Filter = "";
			DB->TabZones->Filtered = false;
			DB->TabZones->Refresh();
		}
		while( DB->TabControllers->FindNext() == true);
	}

	if( DB->TabProject->FindFirst() )
	{
		DB->TabControllers->Filter = "[CtrlAlarmStatus] = 1";
		DB->TabControllers->Filtered = true;
		if( DB->TabControllers->FindFirst() )
		{
			DB->TabProject->Edit();
			DB->TabProject->FieldValues["PrjAlarmStatus"] = 1;
			DB->TabProject->Post();
		}
		else
		{
			DB->TabProject->Edit();
			DB->TabProject->FieldValues["PrjAlarmStatus"] = 0;
			DB->TabProject->Post();
		}
		DB->TabControllers->Filter = "";
		DB->TabControllers->Filtered = false;
		DB->TabControllers->Refresh();
	}
}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::TimerCapabilityReqEvent(TObject *Sender)
{
  Word NodeAdr;

	TimerCapabilityReq->Enabled = false;
  CapReqCounter = 0;
  if( DB->TabNodes->FindFirst() )
  {
    do
		{
		NodeAdr = DB->TabNodes->FieldByName("NodeCanAdr")->AsInteger;
	  if( ( DB->TabNodes->FieldByName("NodeType")->AsInteger == 0 ) &&
				( DB->TabNodes->FieldByName("NodeStatus")->AsInteger == 0 ))
			{
        RequestCapability( NodeAdr );
				CapReqCounter++;
      }
    }
		while( DB->TabNodes->FindNext() == true);
	}
}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::TimerSetCANGroupEvent(TObject *Sender)
{

Word  NodeAdr, GroupAdr;

TimerSetCANGroup->Enabled = false;
if( DB->TabSensors->FindFirst() )
{
  do
  {
    if( DB->TabSensors->FieldByName("SensorStatus")->AsInteger == 0 )
    {
	  NodeAdr = DB->TabSensors->FieldByName("SensorCanAdr")->AsInteger;
	  DB->TabZones->Locate("ZoneNo", DB->TabSensors->FieldByName("ZoneNo")->AsInteger, NoOpts );
	  GroupAdr = DB->TabZones->FieldByName("ZoneCanAdr")->AsInteger;
      SetGroup( NodeAdr, GroupAdr );
    }
  }
  while( DB->TabSensors->FindNext() == true );
}

if( DB->TabPowerSupply->FindFirst() )
{
  do
  {
	if( DB->TabPowerSupply->FieldByName("PSStatus")->AsInteger == 0 )
    {
	  NodeAdr = DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger;
	  DB->TabZones->Locate("ZoneNo", DB->TabPowerSupply->FieldByName("ZoneNo")->AsInteger, NoOpts );
	  GroupAdr = DB->TabZones->FieldByName("ZoneCanAdr")->AsInteger;
      SetGroup( NodeAdr, GroupAdr );
    }
  }
  while( DB->TabPowerSupply->FindNext() == true);
}

}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::TimerIShuntReqEvent(TObject *Sender)
{
	TDateTime NextReq;

	TimerIShuntReq->Enabled = false;
	if( DB->TabSensors->FindFirst() )
	{
		do
		{
		  if( DB->TabSensors->FieldByName("SensorType")->AsInteger == 17 )
		  {
			if( DB->TabSensors->FieldByName("SensorStatus")->AsInteger == 0 )
			{
			  RequestRShunt( DB->TabSensors->FieldByName("SensorCanAdr")->AsInteger );
			}
		  }
		  else
		  {
			if( DB->TabSensors->FieldByName("SensorStatus")->AsInteger == 0 )
			{
			  RequestIShunt( DB->TabSensors->FieldByName("SensorCanAdr")->AsInteger );
			}
		  }

		NextReq = Now() + 100 * One_mS;
		do{}
		while( Now() < NextReq );

		}
		while( DB->TabSensors->FindNext() == true );
	}

	if( DB->TabPowerSupply->FindFirst() )
	{
		do
		{
		if( DB->TabPowerSupply->FieldByName("PSStatus")->AsInteger == 0 )
			{
			RequestIShunt( DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger );
			}
		}
		while( DB->TabPowerSupply->FindNext() == true );
	}
}
//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::TimerVerReqEvent(TObject *Sender)
{
	TimerVerReq->Enabled = false;
	if( DB->TabSensors->FindFirst() )
	{
		do
		{
		if( DB->TabSensors->FieldByName("SensorStatus")->AsInteger == 0 )
			{
			RequestVer( DB->TabSensors->FieldByName("SensorCanAdr")->AsInteger );
			}
		}
		while( DB->TabSensors->FindNext() == true );
	}

	if( DB->TabPowerSupply->FindFirst() )
	{
		do
		{
		if( DB->TabPowerSupply->FieldByName("PSStatus")->AsInteger == 0 )
			{
			RequestVer( DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger );
			}
		}
		while( DB->TabPowerSupply->FindNext() == true );
	}
}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::TimerRestartEvent(TObject *Sender)
{
	TimerRestart->Enabled = false;
  RestartCanNet();
}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::RestartCanNet()
{
	int NodeCount;

	NodeCount = 0;

	// Set PowerSupply
	if( DB->TabPowerSupply->FindFirst() )
	{
		do
		{
			if( DB->TabPowerSupply->FieldByName("PSStatus")->AsInteger == 0 ) NodeCount++;

			if( !( DB->TabPowerSupply->FieldByName("ZoneNo")->AsInteger == 0 ) ) UpdateCurrentPS();
		}
		while( DB->TabPowerSupply->FindNext() == true );
	}

	if( DB->TabSensors->FindFirst() )
	{
		do
		{
			if( DB->TabSensors->FieldByName("SensorStatus")->AsInteger == 0 ) NodeCount++;
		}
		while( DB->TabSensors->FindNext() == true );
	}

	DB->TabControllers->Locate( "CtrlName", Ctrl, NoOpts );
	DB->TabControllers->Edit();
	DB->TabControllers->FieldValues["NodeCount"] = NodeCount;
	DB->TabControllers->Post();

	if( DB->TabZones->FindFirst() )
	{
		do
		{
			if( !( DB->TabZones->FieldByName("ZoneNo")->AsInteger == 1 ) )
			{
				if( DB->TabZones->FieldByName("RecType")->AsInteger == 1 )
					StartMonitor( DB->TabZones->FieldByName("ZoneNo")->AsInteger, true );

				else if( !( DB->TabZones->FieldByName("RecType")->AsInteger == 0 ) )
					StopRecording( DB->TabZones->FieldByName("ZoneNo")->AsInteger );
			}
		}
    while( DB->TabZones->FindNext() == true );
	}
	SClockStart = Now();
	SClockNextEvent = SClockStart;
	SClockEvent = 0;
	TimerSClock->Enabled = true;

  DB->Log( SystemEvent, RestartCan, High, "", 0, 0 );

}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::WatchLPRStatus(int ZoneNo)
{
DB->TabSensors->Filter = "[ZoneNo] = " + IntToStr(ZoneNo) +
                         " AND [RequestStatus] = -1";
DB->TabSensors->Filtered = true;
if( !DB->TabSensors->FindFirst() ) StopRecording( ZoneNo );

DB->TabSensors->Filter = "";
DB->TabSensors->Filtered = false;
DB->TabSensors->Refresh();
}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::SendAccept(Cardinal SerNo, Word CANAdr)
{
Byte msg[8];
Cardinal flag;

flag = canMSG_STD;
msg[0] = 0;
msg[1] = SerNo & 255;
msg[2] = ( SerNo & 65535 ) >> 8;
msg[3] = SerNo >> 16;
msg[4] = CANAdr & 255;
msg[5] = CANAdr >> 8;
if( CAN->SendMsg( 200, msg, 6, flag ) == 6 )
  #if DebugNetIntLocal == 1
  Debug( "Accept to " + IntToStr(SerNo) )
  #endif
  ;
else
  #if DebugNetIntLocal == 1
  Debug( "TX ERR while sending Accept to " + IntToStr(SerNo) )
  #endif
  ;
}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::RequestCapability(Word CanAdr)
{
Byte msg[8];
Cardinal flag;

flag = canMSG_STD;
msg[0] = 4;
msg[1] = 12;
if( CAN->SendMsg( CanAdr, msg, 2, flag ) == 2 )
  #if DebugNetIntLocal == 1
  Debug( "Capability req on CanAdr" + IntToStr(CanAdr) )
  #endif
  ;
else
  #if DebugNetIntLocal == 1
  Debug( "TX ERR while sending Capability req on CanAdr" + IntToStr(CanAdr) )
  #endif
  ;
}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::SetGroup(Word CanAdr, Word CanGroup)
{
Byte msg[8];
Cardinal flag;

flag = canMSG_STD;
msg[0] = 6;
msg[1] = CanGroup & 255;
msg[2] = CanGroup >> 8;

if( CAN->SendMsg( CanAdr, msg, 3, flag ) == 3 )
  #if DebugNetIntLocal == 1
  Debug( "CanAdr " + IntToStr(CanAdr) + " Assigned to group " + IntToStr(CanGroup) )
  #endif
  ;
else
  #if DebugNetIntLocal == 1
  Debug( "TX ERR while Assigning CanAdr" + IntToStr(CanAdr) )
  #endif
  ;
}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::RequestIShunt(Word CanAdr)
{
Byte msg[8];
Cardinal flag;

flag = canMSG_STD;
msg[0] = 11;

if( CAN->SendMsg( CanAdr, msg, 2, flag ) == 2 )
  #if DebugNetIntLocal == 1
  Debug( "IShunt req on CanAdr " + IntToStr(CanAdr) )
  #endif
  ;
else
  #if DebugNetIntLocal == 1
  Debug( "TX ERR while sending IShunt req on CanAdr " + IntToStr(CanAdr) )
  #endif
  ;
}
//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::RequestRShunt(Word CanAdr)
{
Byte msg[8];
Cardinal flag;

flag = canMSG_STD;
msg[0] = 28;

if( CAN->SendMsg( CanAdr, msg, 2, flag ) == 2 )
  #if DebugNetIntLocal == 1
  Debug( "RShunt req on CanAdr " + IntToStr(CanAdr) )
  #endif
  ;
else
  #if DebugNetIntLocal == 1
  Debug( "TX ERR while sending RShunt req on CanAdr " + IntToStr(CanAdr) )
  #endif
  ;
}
//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::RequestVer(Word CanAdr)
{
Byte msg[8];
Cardinal flag;

flag = canMSG_STD;
msg[0] = 13;

if( CAN->SendMsg( CanAdr, msg, 2, flag ) == 2 )
  #if DebugNetIntLocal == 1
  Debug( "Version req on CanAdr " + IntToStr(CanAdr) )
  #endif
  ;
else
  #if DebugNetIntLocal == 1
  Debug( "TX ERR while sending IShunt req on CanAdr " + IntToStr(CanAdr) )
  #endif
  ;
}
//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::SendClrLPR(Word CanAdr)
{
Byte msg[8];
Cardinal flag;

flag = canMSG_STD;
msg[0] = 12;

if( CAN->SendMsg( CanAdr, msg, 1, flag ) == 1 )
  #if DebugNetIntLocal == 1
  Debug( "LPR accept to " + IntToStr(CanAdr) )
  #endif
  ;
else
  #if DebugNetIntLocal == 1
	Debug( "TX ERR while sending LPR accept to " + IntToStr(CanAdr) )
	#endif
  ;
}

//---------------------------------------------------------------------------

bool __fastcall TCIISNetInterface::UpdateCurrentPS()
{
double  AOut;
TCIISUpdatePS *UPS;

if( !CIINetConnected ) return false;


	//M = new TCIISMonitor( DB, CAN, DebugWin, ZoneNo, Ctrl );
	//Monitors->Add( M );



if(DB->TabPowerSupply->FieldByName("PSType")->AsInteger == 11 )
	{
		switch ( DB->TabPowerSupply->FieldByName("PSMode")->AsInteger )
		{
			case 1: AOut = DB->TabPowerSupply->FieldByName("PSSetVoltage")->AsFloat; break;
			case 2: AOut = DB->TabPowerSupply->FieldByName("PSSetCurrent")->AsFloat; break;
			default: AOut = 0;
		}


		AOut = ( AOut * 1000 )
					 * DB->TabPowerSupply->FieldByName("PSOutGain")->AsFloat
					 + ( DB->TabPowerSupply->FieldByName("PSOutOffset")->AsFloat * 1000 );
					 
		//CAN->SetAOut( DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger, AOut );
		//CAN->SetDigOut( DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger, 0, DB->TabPowerSupply->FieldByName("PSVOutEnabled")->AsBoolean );
		//CAN->SetDigOut( DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger, 1, DB->TabPowerSupply->FieldByName("PSRemote")->AsBoolean );

		UPS = new TCIISUpdatePS( CAN,
														DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger,
														DB->TabPowerSupply->FieldByName("PSType")->AsInteger,
														AOut,
														0,
														0,
														DB->TabPowerSupply->FieldByName("PSVOutEnabled")->AsBoolean,
														DB->TabPowerSupply->FieldByName("PSRemote")->AsBoolean,
														DB->TabPowerSupply->FieldByName("PSMode")->AsInteger
													);

	}
else
	{
		//CAN->SetPSOutputOn( DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger, DB->TabPowerSupply->FieldByName("PSVOutEnabled")->AsBoolean );
		//CAN->SetPSMode( DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger, DB->TabPowerSupply->FieldByName("PSMode")->AsInteger );
		//AOut = DB->TabPowerSupply->FieldByName("PSSetVoltage")->AsFloat * 1000;
		//CAN->SetPSVOut( DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger, AOut );
		//AOut = DB->TabPowerSupply->FieldByName("PSSetCurrent")->AsFloat * 1000;
		//CAN->SetPSIOut( DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger, AOut );

		UPS = new TCIISUpdatePS( CAN,
														DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger,
														DB->TabPowerSupply->FieldByName("PSType")->AsInteger,
														0,
														DB->TabPowerSupply->FieldByName("PSSetVoltage")->AsFloat * 1000,
														DB->TabPowerSupply->FieldByName("PSSetCurrent")->AsFloat * 1000,
														DB->TabPowerSupply->FieldByName("PSVOutEnabled")->AsBoolean,
														false,
														DB->TabPowerSupply->FieldByName("PSMode")->AsInteger
													);

	}

	UPSs->Add(UPS);

	if (TimerUpdatePS->Enabled == false)
	{
		TimerUpdatePS->Enabled = true;
	}

  #if DebugNetIntLocal == 1
	Debug( "UppdateCurrentPS" + IntToStr(DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger) );
	#endif

}
void __fastcall TCIISNetInterface::TimerUpdatePSEvent(TObject *Sender)
{
	TCIISUpdatePS *UPS;


	if (UPSs->Count > 0)
	{
		for( int i = 0; i < UPSs->Count; i++)
		{
			UPS = (TCIISUpdatePS*)UPSs->Items[i];
			UPS->OnTimerEvent();
			if (UPS->UpdatePSReady)
			{
				UPSs->Delete( i );
				delete UPS;
			}
		}
	}
	else
	{
    TimerUpdatePS->Enabled = false;
	}


}
//---------------------------------------------------------------------------

bool __fastcall TCIISNetInterface::StartMonitor(int ZoneNo, bool ReStart )
{
  TCIISMonitor *M;

  if( !CIINetConnected ) return false;

  DB->TabZones->Locate( "ZoneNo", ZoneNo, NoOpts );
  if( DB->TabZones->FieldByName("RecType")->AsInteger != 0 && ReStart == false ) return false;

	M = new TCIISMonitor( DB, CAN, DebugWin, ZoneNo, Ctrl );
	Monitors->Add( M );

  DB->TabControllers->Locate( "CtrlName", Ctrl, NoOpts );
  DB->TabControllers->Edit();
  DB->TabControllers->FieldValues["MonitorCount"] = Monitors->Count;
  DB->TabControllers->Post();

  return true;
}

//---------------------------------------------------------------------------

bool __fastcall TCIISNetInterface::StartLPR(int ZoneNo)
{
  TCIISLPR *LPR;

  if( !CIINetConnected ) return false;

  DB->TabZones->Locate( "ZoneNo", ZoneNo, NoOpts );
  if( DB->TabZones->FieldByName("RecType")->AsInteger != 0 ) return false;

  LPR = new TCIISLPR( DB, CAN, DebugWin, ZoneNo, Ctrl );
  LPRs->Add( LPR );

  DB->TabControllers->Locate( "CtrlName", Ctrl, NoOpts );
  DB->TabControllers->Edit();
  DB->TabControllers->FieldValues["LPRCount"] = LPRs->Count;
  DB->TabControllers->Post();

  return true;
}

//---------------------------------------------------------------------------

bool __fastcall TCIISNetInterface::StartDecay(int ZoneNo)
{
  TCIISDecay *D;

  if( !CIINetConnected ) return false;

  DB->TabZones->Locate( "ZoneNo", ZoneNo, NoOpts );
  if( DB->TabZones->FieldByName("RecType")->AsInteger != 0 ) return false;

  D = new TCIISDecay( DB, CAN, DebugWin, ZoneNo, Ctrl );
  Decays->Add( D );

  DB->TabControllers->Locate( "CtrlName", Ctrl, NoOpts );
  DB->TabControllers->Edit();
  DB->TabControllers->FieldValues["DecayCount"] = Decays->Count;
  DB->TabControllers->Post();

  return true;
}

bool __fastcall TCIISNetInterface::StopRecording(int ZoneNo)
{
  TCIISMonitor *M;
  TCIISDecay *D;
  TCIISLPR *LPR;

  if( !CIINetConnected ) return false;

  DB->TabZones->Locate( "ZoneNo", ZoneNo, NoOpts );
  if( DB->TabZones->FieldByName("RecType")->AsInteger == 0 ) return false;

  DB->TabControllers->Locate( "CtrlName", Ctrl, NoOpts );
  
  // Monitors
  for( int i = 0; i < Monitors->Count; i++)
  {
    M = (TCIISMonitor*)Monitors->Items[i];
    if( M->ZoneNo == ZoneNo )
    {
    Monitors->Delete( i );
    delete M;
    };
  }
  DB->TabControllers->Edit();
  DB->TabControllers->FieldValues["MonitorCount"] = Monitors->Count;
  DB->TabControllers->Post();

  // Decays
  for( int i = 0; i < Decays->Count; i++)
  {
    D = (TCIISDecay*)Decays->Items[i];
    if( D->ZoneNo == ZoneNo )
    {
    Decays->Delete( i );
    delete D;
    };
  }
  DB->TabControllers->Edit();
  DB->TabControllers->FieldValues["DecayCount"] = Decays->Count;
  DB->TabControllers->Post();

	// LPRs
  for( int i = 0; i < LPRs->Count; i++)
  {
    LPR = (TCIISLPR*)LPRs->Items[i];
    if( LPR->ZoneNo == ZoneNo )
    {
    LPRs->Delete( i );
    delete LPR;
    };
  }
  DB->TabControllers->Edit();
	DB->TabControllers->FieldValues["LPRCount"] = LPRs->Count;
  DB->TabControllers->Post();

  DB->TabZones->Locate( "ZoneNo", ZoneNo, NoOpts );
  DB->TabZones->Edit();
  DB->TabZones->FieldValues["RecType"] = 0;
  DB->TabZones->Post();

  return true;
}

//---------------------------------------------------------------------------

bool __fastcall TCIISNetInterface::ResetCanNet()
{
  Byte msg[8];
  Cardinal flag;
  TCIISMonitor *M;
  TCIISDecay *D;
  TCIISLPR *LPR;

	TimerSClock->Enabled = false;

	CAN->CanBusOff_2();

  for( int i = 0; i < Monitors->Count; i++)
  {
    M = (TCIISMonitor*)Monitors->Items[i];
    Monitors->Delete( i );
    delete M;
  }
  DB->TabControllers->Edit();
  DB->TabControllers->FieldValues["MonitorCount"] = Monitors->Count;
  DB->TabControllers->Post();

  for( int i = 0; i < Decays->Count; i++)
  {
    D = (TCIISDecay*)Decays->Items[i];
    Decays->Delete( i );
    delete D;
  }
  DB->TabControllers->Edit();
  DB->TabControllers->FieldValues["DecayCount"] = Decays->Count;
  DB->TabControllers->Post();

  for( int i = 0; i < Monitors->Count; i++)
  {
    LPR = (TCIISLPR*)LPRs->Items[i];
    LPRs->Delete( i );
    delete LPR;
  }
  DB->TabControllers->Edit();
  DB->TabControllers->FieldValues["LPRCount"] = LPRs->Count;
  DB->TabControllers->Post();

  DB->TabControllers->Locate( "CtrlName", Ctrl, NoOpts );
  DB->TabControllers->Edit();
  DB->TabControllers->FieldValues["NextCanAdr"] = 300;
  DB->TabControllers->FieldValues["NodeCount"] = 0;
  DB->TabControllers->FieldValues["USBCANStatus"] = 0;
  DB->TabControllers->Post();

  if( DB->TabNodes->FindFirst() )
  {
    do
    {
      DB->TabNodes->Edit();
      DB->TabNodes->FieldValues["NodeCanAdr"] = 0;
      DB->TabNodes->FieldValues["NodeType"] = 0;
			DB->TabNodes->FieldValues["NodeStatus"] = 1;
      DB->TabNodes->FieldValues["NodeConnected"] = false;
      DB->TabNodes->Post();
    }
    while( DB->TabNodes->FindNext() == true);
  }

  if( DB->TabSensors->FindFirst() )
  {
    do
    {
      DB->TabSensors->Edit();
      DB->TabSensors->FieldValues["SensorCanAdr"] = 0;
      DB->TabSensors->FieldValues["SensorType"] = 0;
      DB->TabSensors->FieldValues["SensorStatus"] = 1;
      DB->TabSensors->FieldValues["SensorConnected"] = false;
      DB->TabSensors->Post();
    }
    while( DB->TabSensors->FindNext() == true);
  }

  if( DB->TabPowerSupply->FindFirst() )
  {
    do
    {
      DB->TabPowerSupply->Edit();
      DB->TabPowerSupply->FieldValues["PSCanAdr"] = 0;
      DB->TabPowerSupply->FieldValues["PSType"] = 0;
      DB->TabPowerSupply->FieldValues["PSStatus"] = 1;
      DB->TabPowerSupply->FieldValues["PSConnected"] = false;
      DB->TabPowerSupply->Post();
    }
    while( DB->TabPowerSupply->FindNext() == true);
  }

    DB->TabZones->Filter = "";
    DB->TabZones->Filtered = false;
    DB->TabZones->Refresh();

  if( DB->TabZones->FindFirst() )
  {
    do
    {
      DB->TabZones->Edit();
      DB->TabZones->FieldValues["ZoneCanAdr"] = GetCanAdr();
      DB->TabZones->Post();
    }
    while( DB->TabZones->FindNext() == true);
  }

	CIINetConnected = CAN->CanBusOn();

  if( CIINetConnected )
  {
    flag = canMSG_STD;
    msg[0] = 1;
		if( CAN->SendMsg( 200, msg, 1, flag ) == 1 )
		{
      #if DebugNetIntLocal == 1
      Debug( "Forcing network reset" );
      #endif
			TimerRestart->Enabled = true;
    }
      else
    {
      #if DebugNetIntLocal == 1
      Debug( "TX ERR while forcing network reset " );
      #endif
      CIINetConnected = false;
    }
  }

	if( CIINetConnected )
  {
    DB->TabControllers->Locate( "CtrlName", Ctrl, NoOpts );
    DB->TabControllers->Edit();
    DB->TabControllers->FieldValues["USBCANStatus"] = 1;
    DB->TabControllers->Post();
  }

  DB->Log( SystemEvent, ResetCan, High, "", 0, 0 );

  return CIINetConnected;
}

//---------------------------------------------------------------------------

bool __fastcall TCIISNetInterface::UpdateLastValue(int ZoneNo, int NodeSerialNo)
{
  String  Filter;
  Byte msg[8];
  Cardinal flag;
  Word  CanAdr;

  if( !CIINetConnected ) return false;

  Filter = "";
  flag = canMSG_STD;
  msg[0] = 14;
  msg[1] = 0; //RStatus always 0 fore Last value request

  if( NodeSerialNo == 0 )
  {
    if( ZoneNo != 0 ) Filter = "[ZoneNo] = " + IntToStr(ZoneNo);
    DB->TabZones->Filter = Filter;
    DB->TabZones->Filtered = true;
    if( DB->TabZones->FindFirst() )
    do
    {
	  CanAdr = DB->TabZones->FieldByName("ZoneCanAdr")->AsInteger;

      if( CAN->SendMsg( CanAdr, msg, 2, flag ) == 2 )
        #if DebugNetIntLocal == 1
        Debug( "LastValue req Zone " + IntToStr(ZoneNo) + " CanAdr " + IntToStr(CanAdr) )
        #endif
        ;
      else
        #if DebugNetIntLocal == 1
        Debug( "TX ERR while sending LastValue req Zone " + IntToStr(ZoneNo) + " CanAdr " + IntToStr(CanAdr) )
        #endif
        ;
    }
    while( DB->TabZones->FindNext() == true);

    DB->TabZones->Filter = "";
    DB->TabZones->Filtered = false;
    DB->TabZones->Refresh();
  }
  else
  {
    if( DB->TabNodes->Locate("NodeSerialNo", NodeSerialNo, NoOpts) )
    {
	  CanAdr = DB->TabNodes->FieldByName("NodeCanAdr")->AsInteger;

      if( CAN->SendMsg( CanAdr, msg, 2, flag ) == 2 )
        #if DebugNetIntLocal == 1
        Debug( "LastValue req Node " + IntToStr(NodeSerialNo) + " CanAdr " + IntToStr(CanAdr) )
        #endif
        ;
      else
        #if DebugNetIntLocal == 1
        Debug( "TX ERR while sending LastValue req Node " + IntToStr(NodeSerialNo) + " CanAdr " + IntToStr(CanAdr) )
        #endif
        ;
    }
  }
}

//---------------------------------------------------------------------------

bool __fastcall TCIISNetInterface::UpdateAlarms()
{
        TimerUpdateAlarmsEvent(NULL);
}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::TimerSClockEvent(TObject * Sender)
{
  TCIISMonitor *M;
  TCIISDecay *D;
	bool SchZonesReady;
	__int64 NextEvent_ms;


	if( Now() < SClockNextEvent ) return;

	SClockEvent++;
	NextEvent_ms = SysClock * (__int64)SClockEvent;
	if( SClockEvent == INT_MAX )
	{
		SClockStart += NextEvent_ms * One_mS;
		SClockEvent = 0;
		NextEvent_ms = 0;
	}
	SClockNextEvent = SClockStart + NextEvent_ms * One_mS;

	for( int i = 0; i < Monitors->Count; i++)
	{
		M = (TCIISMonitor*)Monitors->Items[i];
    M->OnTimerEvent();
  }
  for( int i = 0; i < Decays->Count; i++)
  {
    D = (TCIISDecay*)Decays->Items[i];
    D->OnTimerEvent();
    if( D->DecayReady ) StopRecording( D->ZoneNo );
  }

  TSys++;
  if( TSys >= 20 )
  {
    TSys = 0;
    DB->TabControllers->Locate( "CtrlName", Ctrl, NoOpts );

    if( ScheduleStatus > 0 && Now() > ScheduleDateTime )
    {
      SchZonesReady = true;
      if( DB->TabZones->FindFirst() )
      {
        do
				{
          switch (DB->TabZones->FieldByName("ZoneScheduleStatus")->AsInteger)
          {
            case 0:
						if(DB->TabZones->FieldByName("RecType")->AsInteger == 1)
							{
							SchZonesReady = false;
							StopRecording( DB->TabZones->FieldByName("ZoneNo")->AsInteger );

							if( DB->TabControllers->FieldByName("ScheduleDecay")->AsBoolean )
									{
										DB->TabZones->Edit();
										DB->TabZones->FieldValues["ZoneScheduleStatus"] = 1;
										DB->TabZones->Post();
									}
							else if( DB->TabControllers->FieldByName("ScheduleLPR")->AsBoolean )
									{
										DB->TabZones->Edit();
										DB->TabZones->FieldValues["ZoneScheduleStatus"] = 3;
										DB->TabZones->Post();
									}
							else
									{
										DB->TabZones->Edit();
										DB->TabZones->FieldValues["ZoneScheduleStatus"] = 5;
										DB->TabZones->Post();
									}
								#if DebugNetIntLocal == 1
								Debug( "Scheduling started on Zone " + DB->TabZones->FieldByName("ZoneNo")->AsString );
								#endif
              }
            break;

            case 1:
              #if DebugNetIntLocal == 1
              Debug( "Starting scheduled decay on Zone " + DB->TabZones->FieldByName("ZoneNo")->AsString );
              #endif
              SchZonesReady = false;
							DB->TabZones->Edit();
							DB->TabZones->FieldValues["ZoneScheduleStatus"] = 2;
							DB->TabZones->Post();
							StartDecay( DB->TabZones->FieldByName("ZoneNo")->AsInteger );
            break;

            case 2:
              SchZonesReady = false;
							if(DB->TabZones->FieldByName("RecType")->AsInteger == 0)
              {
							if( DB->TabControllers->FieldByName("ScheduleLPR")->AsBoolean )
                {
                  DB->TabZones->Edit();
                  DB->TabZones->FieldValues["ZoneScheduleStatus"] = 3;
                  DB->TabZones->Post();
                }
                else
                {
                  DB->TabZones->Edit();
                  DB->TabZones->FieldValues["ZoneScheduleStatus"] = 5;
                  DB->TabZones->Post();
                }
              }
            break;

            case 3:
              #if DebugNetIntLocal == 1
              Debug( "Starting scheduled LPR on Zone " + DB->TabZones->FieldByName("ZoneNo")->AsString );
              #endif
              SchZonesReady = false;
							
							DB->TabZones->Edit();
							DB->TabZones->FieldValues["ZoneScheduleStatus"] = 4;
							DB->TabZones->Post();
							StartLPR( DB->TabZones->FieldByName("ZoneNo")->AsInteger );
            break;

            case 4:
              SchZonesReady = false;
							if(DB->TabZones->FieldByName("RecType")->AsInteger == 0)
              {
                  DB->TabZones->Edit();
                  DB->TabZones->FieldValues["ZoneScheduleStatus"] = 5;
                  DB->TabZones->Post();
              }
            break;

            case 5:
              SchZonesReady = false;
              // Set PowerSupply
              if( DB->TabPowerSupply->FindFirst() )
							{
                do
                {
								if( DB->TabPowerSupply->FieldByName("ZoneNo")->AsInteger == DB->TabZones->FieldByName("ZoneNo")->AsInteger )
                  {
										UpdateCurrentPS();
                  }
                }
                while( DB->TabPowerSupply->FindNext() == true );
              }

							DB->TabZones->Edit();
							DB->TabZones->FieldValues["ZoneScheduleStatus"] = 6;
							DB->TabZones->Post();
							StartMonitor( DB->TabZones->FieldByName("ZoneNo")->AsInteger, true );
            break;

            case 6:
              SchZonesReady = true;
              #if DebugNetIntLocal == 1
              Debug( "Scheduling ready on Zone " + DB->TabZones->FieldByName("ZoneNo")->AsString );
              #endif

            break;
          }
        }
        while( DB->TabZones->FindNext() == true);
      } // if( DB->TabZones->FindFirst() )

      if( SchZonesReady == true )
      {
        int T, Y;
        Word Year, Month, Day, Hour, Min, Sec, MSec;
        TDateTime DT;

        if( DB->TabZones->FindFirst() )
        {
          do
          {
            DB->TabZones->Edit();
            DB->TabZones->FieldValues["ZoneScheduleStatus"] = 0;
            DB->TabZones->Post();
          }
          while( DB->TabZones->FindNext() == true);
        }

				T = DB->TabControllers->FieldByName("SchedulePeriod")->AsInteger;
        DT = DB->TabControllers->FieldByName("ScheduleDateTime")->AsDateTime;

        switch (DB->TabControllers->FieldByName("SchedulePeriodUnit")->AsInteger)
        {
          case 0: DT = DT + T * OneMinute; // minutes
          break;
          case 1: DT = DT + T * OneHour; // hours
          break;
          case 2: DT = DT + T * OneDay; // days
          break;
          case 3:  // months
            DecodeDate(DT, Year, Month, Day);
            DecodeTime(DT, Hour, Min, Sec, MSec);
            Y = T / 12;
            T = T - Y * 12;
            Month += T;
            Year += Y;
            if( Month > 12 )
            {
              Year++;
              Month -=12;
						}

					 try
					 {
							DT = EncodeDate( Year, Month, Day );
					 }
					 catch(...)
					 {
						 try
						 {
								DT = EncodeDate( Year, Month, 30 );
						 }
						 catch(...)
						 {
							 try
							 {
									DT = EncodeDate( Year, Month, 29 );
							 }
							 catch(...)
							 {
									DT = EncodeDate( Year, Month, 28 );
							 }
						 }
					 }

           DT = DT + EncodeTime( Hour, Min, Sec, MSec );
          break;
        }
        DB->TabControllers->Edit();
		    DB->TabControllers->FieldValues["ScheduleDateTime"] = DT;
        DB->TabControllers->Post();
        ScheduleDateTime = DT;

        #if DebugNetIntLocal == 1
        Debug( "Scheduling ready new scheduling time set" );
        #endif


      } // if( SchZonesReady == true )
    }  // if( ScheduleStatus > 0 && ScheduleDateTime < Now() )
  }
}

//---------------------------------------------------------------------------

void __fastcall TCIISNetInterface::SetDebugWin(TDebugWin *SetDebugWin)
{
  TCIISMonitor *M;
  TCIISDecay *D;
  TCIISLPR *LPR;

  DW = SetDebugWin;

  //CAN interface
  CAN->SetDebugWin( SetDebugWin );

  // Monitors
  for( int i = 0; i < Monitors->Count; i++)
  {
    M = (TCIISMonitor*)Monitors->Items[i];
    M->SetDebugWin ( SetDebugWin );
  }

  // Decays
  for( int i = 0; i < Decays->Count; i++)
  {
    D = (TCIISDecay*)Decays->Items[i];
    D->SetDebugWin( SetDebugWin );
  }


  // LPRs
  for( int i = 0; i < LPRs->Count; i++)
  {
		LPR = (TCIISLPR*)LPRs->Items[i];
    LPR->SetDebugWin( SetDebugWin );
  }

}

bool __fastcall TCIISNetInterface::MoveSensor(int SerialNo)
{
  bool Rslt;

  Rslt = false;
  if( DB->TabSensors->Locate("SensorSerialNo", SerialNo, NoOpts ) )
  {
	if( DB->TabZones->Locate( "ZoneNo", DB->TabSensors->FieldByName("ZoneNo")->AsInteger, NoOpts ))
	{
	  SetGroup( DB->TabSensors->FieldByName("SensorCanAdr")->AsInteger, DB->TabZones->FieldByName("ZoneCanAdr")->AsInteger);
	  Rslt = true;
    }

  }

  return Rslt;
}

bool __fastcall TCIISNetInterface::MovePS(int SerialNo)
{
  bool Rslt;

  Rslt = false;
  if( DB->TabPowerSupply->Locate("PSSerialNo", SerialNo, NoOpts ) )
  {
	if( DB->TabZones->Locate( "ZoneNo", DB->TabPowerSupply->FieldByName("ZoneNo")->AsInteger, NoOpts ))
    {
	  SetGroup( DB->TabPowerSupply->FieldByName("PSCanAdr")->AsInteger, DB->TabZones->FieldByName("ZoneCanAdr")->AsInteger);
      Rslt = true;
    }

  }

  return Rslt;
}


bool __fastcall TCIISNetInterface::UpdateScheduleDateTime()
{
  DB->TabControllers->Locate( "CtrlName", Ctrl, NoOpts );
  ScheduleDateTime = DB->TabControllers->FieldByName("ScheduleDateTime")->AsDateTime;
  ScheduleStatus = DB->TabControllers->FieldByName("CtrlScheduleStatus")->AsInteger;

  return true;
}
